
    // 生成私钥
    //     随机生成256位（32字节）的私钥，需使用密码学安全的随机数生成器（如/dev/urandom或OpenSSL的RAND_bytes）。
    // 计算公钥
    //     使用椭圆曲线加密算法（ECDSA）和secp256k1曲线，从私钥推导出公钥。
    //     公钥为椭圆曲线上的点，格式为非压缩公钥（65字节，包含前缀0x04）。
    // 计算公钥哈希
    //     对公钥进行Keccak-256哈希（TRON官方标准，需替换OpenSSL的SHA3调用）。
    //     取哈希值的最后20字节作为原始地址。
    // 添加前缀和校验和
    //     在原始地址前添加0x41（TRON地址前缀），形成21字节数据。
    //     计算双重SHA256哈希作为校验和，取前4字节附加到地址末尾。
    //     对完整数据（25字节）进行Base58Check编码，得到最终地址（以T开头）。


#include <stdio.h>
#include <secp256k1.h>
#include <string.h>
#include <libkeccak.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <libbase58.h>
#include <time.h>
#include <unistd.h>
#include <stdatomic.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>

#define PROCESSES 1

volatile sig_atomic_t keep_running = 1;

void double_sha256_evp(const uint8_t *data, size_t len, uint8_t *output) {
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    const EVP_MD *md = EVP_sha256();
    uint8_t hash1[32];  // 第一次 SHA-256 结果
    uint8_t hash2[32];  // 第二次 SHA-256 结果
    // 第一次 SHA-256
    EVP_DigestInit_ex(ctx, md, NULL);
    EVP_DigestUpdate(ctx, data, len);
    EVP_DigestFinal_ex(ctx, hash1, NULL);
    // 第二次 SHA-256（对第一次的结果再哈希）
    EVP_DigestInit_ex(ctx, md, NULL);
    EVP_DigestUpdate(ctx, hash1, 32);
    EVP_DigestFinal_ex(ctx, hash2, NULL);
    // 提取第二次哈希的前 4 字节
    memcpy(output, hash2, 4);
    EVP_MD_CTX_free(ctx);
}

void generate_random_tronaddress(secp256k1_context *ctx, FILE *output) {
    unsigned char private_key[32];
    // 生成一个32字节的私钥
    FILE *rand = fopen("/dev/urandom", "rb");
    fread(private_key, 1, 32, rand);
    fclose(rand);
    // 创建公钥
    secp256k1_pubkey pubkey;
    if (!secp256k1_ec_pubkey_create(ctx, &pubkey, private_key)) {
        fprintf(stderr, "Failed to compute public key\n");
        return;
    }
    // 序列化公钥
    unsigned char full_pubkey[65];
    size_t full_len = sizeof(full_pubkey);
    secp256k1_ec_pubkey_serialize(ctx, full_pubkey, &full_len, &pubkey, SECP256K1_EC_UNCOMPRESSED);
    // 提取 64 字节的 X + Y（去掉 04 前缀）
    const uint8_t *xy_pubkey = full_pubkey + 1;    

    struct libkeccak_state state;
    struct libkeccak_spec spec;

    libkeccak_spec_sha3(&spec, 256);

    libkeccak_state_initialise(&state, &spec);
    libkeccak_update(&state, xy_pubkey, 64);
    uint8_t hash[32];
    libkeccak_digest(&state, NULL, 0, 0, NULL, hash);

    uint8_t rawdata[25];
    rawdata[0] = 0x41;
    memcpy(rawdata + 1, hash + 12, 20);
    double_sha256_evp(rawdata, 21, rawdata + 21);

    char tron_address[35];
    size_t tron_address_len = sizeof(tron_address);
    b58enc(tron_address, &tron_address_len, rawdata, sizeof(rawdata));
    if (tron_address[33] == tron_address[32] && tron_address[32] == tron_address[31] && tron_address[31] == tron_address[30]) {
        for (int i = 0; i < 32; i++) {
            fprintf(output, "%02x", private_key[i]);
        }
        fprintf(output, " %s\n", tron_address);
    }
}

void process(int n) {
    secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); 

    char filename[20];
    sprintf(filename, "data/r%d.txt", n); 
    FILE *file = fopen(filename, "a");

    // 测试速度
    clock_t start = clock();
    for (int i = 0; i < 20000; i++) {
        generate_random_tronaddress(ctx, file);
    }
    clock_t end = clock(); // 结束计时
    double cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; // 转换为秒
    double speed = 20000 / cpu_time_used;
    printf("speed: %f address/s\n", speed);

    // 进行主要生产
    while (keep_running == 1) {
        generate_random_tronaddress(ctx, file);
    }

    // 清理工作
    fclose(file);
    secp256k1_context_destroy(ctx);
}

// 信号处理函数（父进程捕获SIGINT）
void handle_sigint(int sig) {
    printf("\nParent: Caught SIGINT, terminating children...\n");
    keep_running = 0; // 通知所有子进程退出
}

int main() {
	pid_t pids[PROCESSES];

    // 父进程设置信号处理
    signal(SIGINT, handle_sigint);

    // 创建进程
    for (int i = 0; i < PROCESSES; i++) {
        pids[i] = fork();
        if (pids[i] == 0) {
            process(i);
        }
    }
    // 等待进程结束
    for (int i = 0; i < PROCESSES; i++) {
        waitpid(pids[i], NULL, 0);
    }

	return 0;
}